<template>
  <div class="container">
    <h1>JSON格式化工具</h1>
    <div class="note">在线JSON格式化工具，可帮助您格式化和美化JSON数据</div>

    <div class="main-content">
      <div class="panel">
        <div class="input-section">
          <label for="json-input">原始JSON数据:</label>
          <textarea id="json-input" v-model="inputJson" placeholder="请输入JSON数据..." @input="clearOutput"></textarea>
        </div>

        <div class="output-section">
          <label>格式化结果:</label>
          <div class="output-content" v-if="formattedJson && !isError">
            <pre class="json-display"><code v-html="highlightedJson"></code></pre>
          </div>
          <div class="output-content error" v-else-if="isError">
            <pre class="json-error"><code>{{ formattedJson }}</code></pre>
          </div>
          <div class="output-placeholder" v-else>
            格式化后的JSON将在此处显示
          </div>
        </div>
      </div>
    </div>

    <div class="controls">
      <button @click="formatJson" class="format-btn">JSON格式化</button>
      <button @click="removeEscape" class="unescape-btn">去除转义</button>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, computed } from 'vue'

const inputJson = ref<string>('')
const formattedJson = ref<string>('')
const isError = ref<boolean>(false)

// 清空输出内容
function clearOutput() {
  formattedJson.value = ''
  isError.value = false
}

// JSON语法高亮
const highlightedJson = computed(() => {
  if (!formattedJson.value) return ''

  return formattedJson.value
    .replace(/&/g, '&amp;')
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;')
    .replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g, (match) => {
      let cls = 'number'
      if (/^"/.test(match)) {
        if (/:$/.test(match)) {
          cls = 'key'
        } else {
          cls = 'string'
        }
      } else if (/true|false/.test(match)) {
        cls = 'boolean'
      } else if (/null/.test(match)) {
        cls = 'null'
      }
      return `<span class="${cls}">${match}</span>`
    })
})

// JSON格式化功能
function formatJson() {
  if (!inputJson.value.trim()) {
    formattedJson.value = ''
    isError.value = false
    return
  }

  try {
    const parsed = JSON.parse(inputJson.value)
    formattedJson.value = JSON.stringify(parsed, null, 2)
    isError.value = false
  } catch (error) {
    formattedJson.value = `JSON格式错误: ${(error as Error).message}`
    isError.value = true
  }
}

// 去除转义字符功能
function removeEscape() {
  if (!inputJson.value.trim()) {
    formattedJson.value = ''
    isError.value = false
    return
  }

  try {
    // 先尝试解析原始输入，确保是有效的JSON
    const parsed = JSON.parse(inputJson.value)
    // 然后重新序列化，去除不必要的转义字符
    formattedJson.value = JSON.stringify(parsed, null, 2)
    isError.value = false
  } catch (error) {
    // 如果原始输入不是有效的JSON，尝试去除转义字符后再解析
    try {
      const unescaped = inputJson.value.replace(/\\(["\\/bfnrt])/g, (match, p1) => {
        const escapes: Record<string, string> = {
          '"': '"',
          '\\': '\\',
          '/': '/',
          'b': '\b',
          'f': '\f',
          'n': '\n',
          'r': '\r',
          't': '\t'
        }
        return escapes[p1] || p1
      })
      const parsed = JSON.parse(unescaped)
      formattedJson.value = JSON.stringify(parsed, null, 2)
      isError.value = false
    } catch (innerError) {
      formattedJson.value = `JSON格式错误: ${(innerError as Error).message}`
      isError.value = true
    }
  }
}
</script>

<style scoped>
.container {
  display: flex;
  flex-direction: column;
  height: 80vh;
  max-width: 90%;
  margin: 0 auto;
  font-family: Arial, Helvetica, sans-serif;
  color: #222;
  padding: 16px;
  box-sizing: border-box;
  margin: 0 auto;
  gap: 16px;
}

h1 {
  margin: 0;
  font-size: 20px;
  text-align: center;
  padding-bottom: 8px;
}

.note {
  color: #4b5563;
  font-size: 14px;
  text-align: center;
}

.main-content {
  min-height: 60%;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.panel {
  display: flex;
  flex: 1;
  gap: 20px;
  overflow: hidden;
}

.input-section,
.output-section {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 8px;
  overflow: hidden;
}

.input-section label,
.output-section label {
  font-weight: bold;
  font-size: 14px;
}

textarea {
  height: 100%;
  /* 最大高度 */
  padding: 12px;
  border: 1px solid #d0d7de;
  border-radius: 6px;
  font-family: JetBrains Mono, Consolas, monospace;
  font-size: 14px;
  resize: none;
  overflow: auto;
  box-sizing: border-box;
}

.output-content {
  height: 100%;
  padding: 12px;
  border: 1px solid #d0d7de;
  border-radius: 6px;
  background-color: #2F2F2F;
  overflow-x: auto;
  /* 水平滚动 */
  overflow-y: auto;
  /* 垂直滚动 */
  white-space: pre;
  word-break: keep-all;
  word-wrap: normal;
  width: 100%;
  box-sizing: border-box;
}

.output-placeholder {
  height: 100%;
  /* 最大高度 */
  padding: 12px;
  border: 1px solid #d0d7de;
  border-radius: 6px;
  background-color: #f6f8fa;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #6c757d;
  font-style: italic;
}

/* JSON 高亮样式 */
.json-display {
  font-family: Arial, Helvetica, sans-serif;
  font-size: 16px;
  font-weight: bold;
  line-height: 1.2;
  color: #bdcdd9;
  margin: 0;
  white-space: pre;
  word-break: keep-all;
  overflow-x: visible;
  display: table;
  width: max-content;
  max-width: max-content;
}

.json-display :deep(.key) {
  color: #b35fa7;
}

.json-display :deep(.string) {
  color: #059905;
}

.json-display :deep(.number) {
  color: #ee422e;
}

.json-display :deep(.boolean) {
  color: #db946e;
}

.json-display :deep(.null) {
  color: #800080;
}

.json-error {
  font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, "Roboto Mono", monospace;
  font-size: 14px;
  line-height: 1.4;
  margin: 0;
  color: #dc3545;
}

.controls {
  display: flex;
  gap: 12px;
  justify-content: center;
  padding: 16px 0;
}

.format-btn,
.unescape-btn {
  padding: 8px 16px;
  border: none;
  border-radius: 6px;
  cursor: pointer;
  font-weight: bold;
  transition: background-color 0.3s;
}

.format-btn {
  background-color: #2196F3;
  color: white;
}

.format-btn:hover {
  background-color: #0b7dda;
}

.unescape-btn {
  background-color: #4CAF50;
  color: white;
}

.unescape-btn:hover {
  background-color: #45a049;
}

@media (max-width: 768px) {
  .panel {
    flex-direction: column;
  }

  textarea,
  .output-content,
  .output-placeholder {
    height: 300px;
    /* 在小屏幕上调整高度 */
    min-height: 300px;
    max-height: 300px;
    box-sizing: border-box;
  }
}
</style>